﻿//
// Created by 25007 on 2023/2/21.
//

#ifndef FFMPEG_PLAYER_MQTT_NO_TS_SERVER_H
#define FFMPEG_PLAYER_MQTT_NO_TS_SERVER_H
# if acl
#include <iostream>
#include <set>
#include <mqtt_server_cpp.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/composite_key.hpp>
#include "net/base_net.h"
#include "log.h"

// 多索引容器
namespace mi = boost::multi_index;

class MqttNoTsServer : public BaseNet {
private:

    using con_t = MQTT_NS::server<>::endpoint_t;
    using con_sp_t = std::shared_ptr<con_t>;

    struct sub_con {
        sub_con(MQTT_NS::buffer topic, con_sp_t con, MQTT_NS::qos qos_value)
                : topic(std::move(topic)), con(std::move(con)), qos_value(qos_value) {}

        MQTT_NS::buffer topic;
        con_sp_t con;
        MQTT_NS::qos qos_value;
    };

    // 如果要把sub_con某个属性字段设置为搜索引擎，则需要定义用于排序的空结构体对象
    struct tag_topic {
    };
    struct tag_con {
    };
    struct tag_con_topic {
    };

    //  BOOST_MULTI_INDEX_MEMBER(索引源的对象或者结构体类型, index_item的类型 ,  index_item ),
    // 定义一个multi_index_container（多索引容器）
    using mi_sub_con = mi::multi_index_container<
            sub_con,
            mi::indexed_by<
                    mi::ordered_unique<
                            mi::tag<tag_con_topic>,
                            mi::composite_key<
                                    sub_con,
                                    BOOST_MULTI_INDEX_MEMBER(sub_con, con_sp_t, con),
                                    BOOST_MULTI_INDEX_MEMBER(sub_con, MQTT_NS::buffer, topic)
                            >
                    >,//con 与 topic 联合主键
                    mi::ordered_non_unique<
                            mi::tag<tag_topic>,
                            BOOST_MULTI_INDEX_MEMBER(sub_con, MQTT_NS::buffer, topic)
                    >,//topic 非唯一索引
                    mi::ordered_non_unique<
                            mi::tag<tag_con>,
                            BOOST_MULTI_INDEX_MEMBER(sub_con, con_sp_t, con)
                    > //con  非唯一索引
            >
    >;

    inline void close_proc(std::set<con_sp_t> &cons, mi_sub_con &subs, con_sp_t const &con) {
        cons.erase(con);

        auto &idx = subs.get<tag_con>();
        auto r = idx.equal_range(con);
        idx.erase(r.first, r.second);
    }

    // event loop
    boost::asio::io_context ioc;

    // 链接集合
    std::set<con_sp_t> connections;

    // 订阅集合
    mi_sub_con subs;

    // server
    mqtt::server<> *server;


public:
    void init() override;

    void run() override;

    virtual ~MqttNoTsServer();
};
#endif
#endif //FFMPEG_PLAYER_MQTT_NO_TS_SERVER_H
